--In Search of The Most Amazing Thing--
A 4am crack                  2019-11-29
---------------------------------------

Name: In Search of The Most Amazing
  Thing
Version: rev. 0 (*)
Genre: educational
Year: 1983
Credits: Tom Snyder, Omar H. Khudari
Publisher: Spinnaker Software
Platform: Apple ][+ or later
Media: 5.25-inch disk
Sides: 1
OS: DOS 3.3 with custom bootloader and
  Pronto-DOS after-loader

(*) This game was re-released at least
    twice with productized protections.
    I believe this one is the first
    release.

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  immediate disk read error

Locksmith Fast Disk Backup
  unable to read any track

EDD 4 bit copy (no sync, no count)
  no errors, but copy grinds the disk
  forever like it can't read itself

Copy ][+ nibble editor
  The disk appears to use 16 sectors.
  I can see a relatively standard
  sector structure on every track. It
  seems to use a per-track address
  prologue (sometimes $AA $D5 $AB,
  sometimes $BF $AA $D5) and data
  prologue (sometimes $ED $AA $D5,
  sometimes $D7 $AA $D5).

Disk Fixer
  attempts to use read sectors with the
  prologues and epilogues I saw in the
  nibble editor were unsuccessful.
  Maybe a non-standard nibble translate
  table as well?

Why didn't COPYA work?
  modified prologues and epilogues and
  probably some other stuff

Why didn't Locksmith FDB work?
  ditto

Why didn't my EDD copy work?
  I don't know.

Next steps:

  1. Trace the boot
  2. Capture the RWTS
  3. Convert the disk to a standard
     format
  4. Declare victory (*)

(*) go to the gym

                   ~

               Chapter 1
     In Which We Sharpen Our Wits
           And Our Pencils,
        And Our Journey Begins


Our journey starts, as so many journeys
in copy protection start, by copying
the drive firmware to lower memory and
modifying it.

*9600<C600.C6FFM

; copy the boot sector to higher memory
; so it survives a reboot
96F8-   A0 00       LDY   #$00
96FA-   B9 00 08    LDA   $0800,Y
96FD-   99 00 28    STA   $2800,Y
9700-   C8          INY
9701-   D0 F7       BNE   $96FA

; turn off slot 6 drive motor and
; reboot to my work disk in slot 5
9703-   AD E8 C0    LDA   $C0E8
9706-   4C 00 C5    JMP   $C500

*BSAVE TRACE0,A$9600,L$109
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE OBJ.0800-08FF,A$2800,L$100
]CALL -151

*800<2800.28FFM
*801L

; relocate this code to lower memory
0801-   A2 00       LDX   #$00
0803-   BD 00 08    LDA   $0800,X
0806-   9D 00 02    STA   $0200,X
0809-   E8          INX
080A-   D0 F7       BNE   $0803

; and continue there
080C-   4C 0F 02    JMP   $020F

So the rest of this will run from $020F
instead of $080F.

; clear text page 2
080F-   A9 A0       LDA   #$A0
0811-   9D 00 08    STA   $0800,X
0814-   9D 00 09    STA   $0900,X
0817-   9D 00 0A    STA   $0A00,X
081A-   9D 00 0B    STA   $0B00,X
081D-   E8          INX
081E-   D0 F1       BNE   $0811

; show text page 2
0820-   AD 55 C0    LDA   $C055

; print "SPINNAKER" on the top line
0823-   A2 09       LDX   #$09
0825-   BD E9 02    LDA   $02E9,X
0828-   9D 0E 08    STA   $080E,X
082B-   CA          DEX
082C-   10 F7       BPL   $0825

; These are the zero page locations
; used by the drive firmware. If we're
; using them in the same, way, we will
; be loading a single sector from track
; 0 into $0400..$04FF.
082E-   A9 00       LDA   #$00
0830-   85 26       STA   $26
0832-   85 41       STA   $41
0834-   A9 0D       LDA   #$0D
0836-   85 3D       STA   $3D
0838-   A9 04       LDA   #$04
083A-   85 27       STA   $27
083C-   A6 2B       LDX   $2B
083E-   20 44 02    JSR   $0244

; continue at $0400 (which, presumably,
; we just read)
0841-   4C 00 04    JMP   $0400

However, we are NOT reusing the drive
firmware at $C65C. Instead, we have
an entirely custom routine at $0244,
in memory now at $0844.

*844L

0844-   BD 8C C0    LDA   $C08C,X
0847-   10 FB       BPL   $0844
0849-   49 AA       EOR   #$AA
084B-   D0 F7       BNE   $0844
084D-   BD 8C C0    LDA   $C08C,X
0850-   10 FB       BPL   $084D
0852-   C9 D5       CMP   #$D5
0854-   D0 F3       BNE   $0849
0856-   EA          NOP
0857-   BD 8C C0    LDA   $C08C,X
085A-   10 FB       BPL   $0857
085C-   C9 AB       CMP   #$AB
085E-   F0 02       BEQ   $0862
0860-   D0 E2       BNE   $0844
...[snip]...

It appears to be highly similar to the
drive firmware, except for modified
prologue and epilogue sequences. (Shown
above: looking for an address prologue
of $AA $D5 $AB.)

I'm going to let this routine do its
thing, then interrupt the boot at $0241
instead of continuing to the newly read
code at $0400.

                   ~

               Chapter 2
     In Which We Encounter A Brief
      Repetition of the Main Idea


*9600<C600.C6FFM

; set up callback after reading one
; sector into $0400
96F8-   A9 05       LDA   #$05
96FA-   8D 42 08    STA   $0842
96FD-   A9 97       LDA   #$97
96FF-   8D 43 08    STA   $0843

; start the boot
9702-   4C 01 08    JMP   $0801

; callback is here --
; save code at $0400 to higher memory
; so it survives a reboot
9705-   A0 00       LDY   #$00
9707-   B9 00 04    LDA   $0400,Y
970A-   99 00 24    STA   $2400,Y
970D-   C8          INY
970E-   D0 F7       BNE   $9707

; turn off slot 6 drive motor and
; reboot to my work disk in slot 5
9710-   AD E8 C0    LDA   $C0E8
9713-   4C 00 C5    JMP   $C500

*BSAVE TRACE1,A$9600,L$116
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE OBJ.0400-04FF,A$2400,L$100
]CALL -151

*2400L

; again setting up zero page locations
; to read a single sector, this time
; into $0500
2400-   A9 00       LDA   #$00
2402-   85 26       STA   $26
2404-   85 41       STA   $41
2406-   A9 0B       LDA   #$0B
2408-   85 3D       STA   $3D
240A-   A9 05       LDA   #$05
240C-   85 27       STA   $27
240E-   A6 2B       LDX   $2B

; reusing the same routine we used to
; read a sector into $0400 earlier
2410-   20 44 02    JSR   $0244

; execution continues at the code we
; just read into $0500
2413-   4C 00 05    JMP   $0500

So I get to write a two-phase boot
trace to interrupt the boot at $0413
instead of continuing to $0500.

                   ~

               Chapter 3
     In Which We Encounter A Brief
      Repetition of the Main Idea


*9600<C600.C6FFM

; set up callback #1
96F8-   A9 05       LDA   #$05
96FA-   8D 42 08    STA   $0842
96FD-   A9 97       LDA   #$97
96FF-   8D 43 08    STA   $0843

; start the boot
9702-   4C 01 08    JMP   $0801

; callback #1 is here --
; set up callback #2
9705-   A9 12       LDA   #$12
9707-   8D 14 04    STA   $0414
970A-   A9 97       LDA   #$97
970C-   8D 15 04    STA   $0415

; continue the boot
970F-   4C 00 04    JMP   $0400

; callback #2 is here --
; copy code at $0500 to higher memory
; so it survives a reboot
9712-   A0 00       LDY   #$00
9714-   B9 00 05    LDA   $0500,Y
9717-   99 00 25    STA   $2500,Y
971A-   C8          INY
971B-   D0 F7       BNE   $9714

; turn off slot 6 drive motor and
; reboot to my work disk in slot 5
971D-   AD E8 C0    LDA   $C0E8
9720-   4C 00 C5    JMP   $C500

*BSAVE TRACE2,A$9600,L$123
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE OBJ.0500-05FF,A$2500,L$100
]CALL -151

*2500L

2500-   A9 00       LDA   #$00
2502-   85 26       STA   $26
2504-   85 41       STA   $41
2506-   A9 09       LDA   #$09
2508-   85 3D       STA   $3D
250A-   A9 06       LDA   #$06
250C-   85 27       STA   $27
250E-   A6 2B       LDX   $2B
2510-   20 44 02    JSR   $0244
2513-   4C 00 06    JMP   $0600

You have got to be kidding me.

                   ~

               Chapter 4
     In Which I Am Not Kidding You


Three-phase boot trace, go.

*9600<C600.C6FFM

; set up callback #1
96F8-   A9 05       LDA   #$05
96FA-   8D 42 08    STA   $0842
96FD-   A9 97       LDA   #$97
96FF-   8D 43 08    STA   $0843

; start the boot
9702-   4C 01 08    JMP   $0801

; callback #1 is here --
; set up callback #2
9705-   A9 12       LDA   #$12
9707-   8D 14 04    STA   $0414
970A-   A9 97       LDA   #$97
970C-   8D 15 04    STA   $0415

; continue the boot
970F-   4C 00 04    JMP   $0400

; callback #2 is here --
; set up callback #3
9712-   A9 1F       LDA   #$1F
9714-   8D 14 05    STA   $0514
9717-   A9 97       LDA   #$97
9719-   8D 15 05    STA   $0515

; continue the boot
971C-   4C 00 05    JMP   $0500

; copy code at $0600 to higher memory
; blah blah blah you get the idea
971F-   A0 00       LDY   #$00
9721-   B9 00 06    LDA   $0600,Y
9724-   99 00 26    STA   $2600,Y
9727-   C8          INY
9728-   D0 F7       BNE   $9721

; turn off slot 6 drive motor and
; reboot to my work disk in slot 5
972A-   AD E8 C0    LDA   $C0E8
972D-   4C 00 C5    JMP   $C500

*BSAVE TRACE3,A$9600,L$130
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE OBJ.0600-06FF,A$2600,L$100
]CALL -151

*2600L

2600-   A9 B6       LDA   #$B6
2602-   A0 06       LDY   #$06
2604-   BE C0 05    LDX   $05C0,Y
2607-   9D E4 06    STA   $06E4,X
260A-   18          CLC
260B-   69 01       ADC   #$01
260D-   C8          INY
260E-   C0 10       CPY   #$10
2610-   D0 F2       BNE   $2604

Well at least it's something different.
Also, it's using some data from page 5,
which I captured earlier but is not
currently in memory. Let's fix that.

*BLOAD OBJ.0500-05FF,A$2500
*25C0.

25C0- 00 0D 0B 09 07 05 03 01
25C8- 0E 0C 0A 08 06 04 02 0F

Ah, that appears to be a standard
sector order map which translates
physical sectors to DOS 3.3 logical
sectors. And we're using it to order
values starting at $B6 and going up to
$BF in an array starting at $06E4. I
would guess Those are likely the high
bytes of addresses to store the sectors
we're about to read.

2612-   A6 2B       LDX   $2B
2614-   BD 8C C0    LDA   $C08C,X
2617-   10 FB       BPL   $2614
2619-   49 AA       EOR   #$AA
261B-   D0 F7       BNE   $2614
261D-   BD 8C C0    LDA   $C08C,X
2620-   10 FB       BPL   $261D
2622-   C9 D5       CMP   #$D5
2624-   D0 F3       BNE   $2619
2626-   EA          NOP
2627-   BD 8C C0    LDA   $C08C,X
262A-   10 FB       BPL   $2627
262C-   C9 AB       CMP   #$AB
262E-   D0 E4       BNE   $2614
...[snip]...

This is yet another routine to read
from a slightly altered 16-sector disk.
It's very similar to all the others, so
I won't show all of it. But here is a
relevant chunk in the middle, where it
takes the physical sector ID in zero
page $3D and looks up the target
address in the array at $06E4 that we
constructed earlier.

2648-   A4 3D       LDY   $3D
264A-   B9 E4 06    LDA   $06E4,Y
264D-   F0 C3       BEQ   $2612
264F-   85 27       STA   $27

Once it finishes reading a sector, it
sets the target page to 0:

26B5-   A4 3D       LDY   $3D
26B7-   A9 00       LDA   #$00
26B9-   99 E4 06    STA   $06E4,Y

Then it loops through the entire array
to see if there are any unread sectors
that still have a non-zero target page.

26BC-   A0 0F       LDY   #$0F
26BE-   B9 E4 06    LDA   $06E4,Y
26C1-   F0 03       BEQ   $26C6
26C3-   4C 12 06    JMP   $0612
26C6-   88          DEY
26C7-   10 F5       BPL   $26BE

Once all sectors have been read, we
copy page 5 to page 3. Among other
things, this will set the reset vector
at $03F2.

26C9-   A2 00       LDX   #$00
26CB-   BD 00 05    LDA   $0500,X
26CE-   9D 00 03    STA   $0300,X
26D1-   E8          INX
26D2-   D0 F7       BNE   $26CB

Finally we jump into the newly read
code, with a very familiar looking
jump.

26DF-   A6 2B       LDX   $2B
26E1-   4C 00 B7    JMP   $B700

Out of curiosity, because I am never
not curious about such things, here is
the reset vector and The Badlands
routine:

*25F2.25F3

25F2- 16 03

*2516L

; wipe memory to zero out everything
; we just read from track 0
2516-   A2 00       LDX   #$00
2518-   8A          TXA
2519-   9D 00 B6    STA   $B600,X
251C-   9D 00 B7    STA   $B700,X
251F-   9D 00 B8    STA   $B800,X
2522-   9D 00 B9    STA   $B900,X
2525-   9D 00 BA    STA   $BA00,X
2528-   9D 00 BB    STA   $BB00,X
252B-   9D 00 BC    STA   $BC00,X
252E-   9D 00 BD    STA   $BD00,X
2531-   9D 00 BE    STA   $BE00,X
2534-   9D 00 BF    STA   $BF00,X
2537-   E8          INX
2538-   D0 DF       BNE   $2519

; and reboot
253A-   8D F4 03    STA   $03F4
253D-   4C 62 FA    JMP   $FA62

Well okay then. Let's, as they say, try
not to end up there.

                   ~

               Chapter 5
           In Which We Find
        The Most Amazing Thing


The code at $0600 reads a number of
sectors into $B600..$BFFF before
jumping to $B700 to continue the boot.
Let's interrupt the boot there, with
a [...counts on fingers...] four-phase
boot tracer.

*9600<C600.C6FFM

; set up callback #1
96F8-   A9 05       LDA   #$05
96FA-   8D 42 08    STA   $0842
96FD-   A9 97       LDA   #$97
96FF-   8D 43 08    STA   $0843

; start the boot
9702-   4C 01 08    JMP   $0801

; callback #1 is here --
; set up callback #2
9705-   A9 12       LDA   #$12
9707-   8D 14 04    STA   $0414
970A-   A9 97       LDA   #$97
970C-   8D 15 04    STA   $0415

; continue the boot
970F-   4C 00 04    JMP   $0400

; callback #2 is here --
; set up callback #3
9712-   A9 1F       LDA   #$1F
9714-   8D 14 05    STA   $0514
9717-   A9 97       LDA   #$97
9719-   8D 15 05    STA   $0515

; continue the boot
971C-   4C 00 05    JMP   $0500

; callback #3 is here --
; set up callback #4
971F-   A9 2C       LDA   #$2C
9721-   8D E2 06    STA   $06E2
9724-   A9 97       LDA   #$97
9726-   8D E3 06    STA   $06E3

; continue the boot
9729-   4C 00 06    JMP   $0600

; callback #4 is here --
; copy $B600+ to lower memory so it
; survives a reboot
972C-   A2 0A       LDX   #$0A
972E-   A0 00       LDY   #$00
9730-   B9 00 B6    LDA   $B600,Y
9733-   99 00 26    STA   $2600,Y
9736-   C8          INY
9737-   D0 F7       BNE   $9730
9739-   EE 32 97    INC   $9732
973C-   EE 35 97    INC   $9735
973F-   CA          DEX
9740-   D0 EE       BNE   $9730

; turn off slot 6 drive motor and
; reboot to my work disk in slot 5
9742-   AD E8 C0    LDA   $C0E8
9745-   4C 00 C5    JMP   $C500

*BSAVE TRACE4,A$9600,L$148
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE OBJ.B600-BFFF,A$2600,L$A00

Whew.

]CALL -151

$B700 is in memory at $2700, so let's
start there.

*2700L

2700-   4C EA B6    JMP   $B6EA

$B6EA is in memory at $26EA, &c.

*26EAL

; set Applesoft RUN flag
26EA-   A9 80       LDA   #$80
26EC-   85 D8       STA   $D8
26EE-   8E E9 B7    STX   $B7E9
26F1-   8E F7 B7    STX   $B7F7

; clear screen
26F4-   20 58 FC    JSR   $FC58

; return to text page 1 (remember we've
; been on text page 2 this whole time,
; since the earliest boot sector)
26F7-   AD 54 C0    LDA   $C054
26FA-   AD 10 C0    LDA   $C010

; now continue as normal
26FD-   4C 06 B7    JMP   $B706

; very familiar code here
2706-   A9 01       LDA   #$01
2708-   8D F8 B7    STA   $B7F8
270B-   8D EA B7    STA   $B7EA
270E-   AD E0 B7    LDA   $B7E0
2711-   8D E1 B7    STA   $B7E1
2714-   A9 02       LDA   #$02
2716-   8D EC B7    STA   $B7EC
2719-   A9 08       LDA   #$08
271B-   8D ED B7    STA   $B7ED
271E-   AC E7 B7    LDY   $B7E7
2721-   88          DEY
2722-   8C F1 B7    STY   $B7F1
2725-   A9 01       LDA   #$01
2727-   8D F4 B7    STA   $B7F4
272A-   8A          TXA
272B-   4A          LSR
272C-   4A          LSR
272D-   4A          LSR
272E-   4A          LSR
272F-   20 30 B6    JSR   $B630
2732-   9D F8 04    STA   $04F8,X
2735-   9D 78 04    STA   $0478,X
2738-   20 93 B7    JSR   $B793
273B-   A2 FF       LDX   #$FF
273D-   9A          TXS
273E-   8E EB B7    STX   $B7EB
2741-   4C C8 BF    JMP   $BFC8
2744-   20 89 FE    JSR   $FE89
2747-   4C 84 9D    JMP   $9D84

Other than the starting track/sector
(T02,S08) and the JSR to $B630 (not
shown, harmless), this is identical
to a DOS 3.3 bootloader. That leads
me to believe that we have -- through
the most circuitous of routes -- simply
loaded a DOS 3.3 RWTS into memory.

It has the standard entry point at
$B7B5 (in memory at $27B5):

27B5-   08          PHP
27B6-   78          SEI
27B7-   20 00 BD    JSR   $BD00
27BA-   B0 03       BCS   $27BF
27BC-   28          PLP
27BD-   18          CLC
27BE-   60          RTS
27BF-   28          PLP
27C0-   38          SEC
27C1-   60          RTS

It has the standard entry point at
$BD00 (in memory at $2D00):

*2D00L

2D00-   84 48       STY   $48
2D02-   85 49       STA   $49
2D04-   A0 02       LDY   #$02
2D06-   8C F8 06    STY   $06F8
2D09-   A0 04       LDY   #$04
2D0B-   8C F8 04    STY   $04F8

Other code is not in exactly the same
places. $B944, for example, is usually
the routine to find the next address
prologue and parse the address field.
In this RWTS, it appears to start at
$2983 instead:

2983-   A0 20       LDY   #$20
2985-   88          DEY
2986-   D0 03       BNE   $298B
2988-   4C 17 BA    JMP   $BA17
298B-   BD 8C C0    LDA   $C08C,X
298E-   10 FB       BPL   $298B

; call an RTS to burn 12 cycles
2990-   20 18 BA    JSR   $BA18
2993-   C9 AA       CMP   #$AA

; but then use a BEQ instead of a BNE
; to burn 1 additional cycle (branches
; taken require 3 cycles, but branches
; not taken are only 2 cycles)
2995-   F0 04       BEQ   $299B
2997-   C9 00       CMP   #$00
2999-   D0 EA       BNE   $2985

; then a NOP to burn 2 more cycles
299B-   EA          NOP

; then finally start looking for the
; second nibble of the prologue
299C-   BD 8C C0    LDA   $C08C,X
299F-   10 FB       BPL   $299C
29A1-   C9 D5       CMP   #$D5
29A3-   F0 04       BEQ   $29A9
29A5-   C9 00       CMP   #$00
29A7-   D0 EA       BNE   $2993

It goes on like this for a while: a
combination of normal LDA / BPL loops
and non-standard branches, JSRs, and
NOPs to burn CPU cycles while the disk
is spinning. The nibbles on this disk
are specifically timed so nothing can
read them except this code.

Here, for example, is the code towards
the end of this same routine, which
checks the address epilogue:

; read a nibble
29E8-   BD 8C C0    LDA   $C08C,X
29EB-   10 FB       BPL   $29E8

; pointless compare and branch (never
; taken) to burn 4 cycles
29ED-   C9 00       CMP   #$00
29EF-   F0 26       BEQ   $2A17

; now check the first epilogue nibble
29F1-   C9 ED       CMP   #$ED
29F3-   D0 22       BNE   $2A17

; JSR to an RTS to burn 12 cycles
29F5-   20 18 BA    JSR   $BA18

; NOP x3 will burn 6 more cycles
29F8-   EA          NOP
29F9-   EA          NOP
29FA-   EA          NOP

; check the data latch again -- if the
; next nibble is already here, that's
; an error and indicates that we're on
; an unauthorized copy that did not
; preserve all the timing bits between
; these nibbles
29FB-   BD 8C C0    LDA   $C08C,X
29FE-   30 17       BMI   $2A17
2A00-   EA          NOP

(This is where our unsuccessful EDD bit
copy fails.)

; now, finally, look for the second
; epilogue nibble
2A01-   BD 8C C0    LDA   $C08C,X
2A04-   10 FB       BPL   $2A01
2A06-   C9 AA       CMP   #$AA
2A08-   D0 0D       BNE   $2A17

; oh hey, and the THIRD epilogue nibble
; is actually used somehow, not to be
; checked directly but to look up some
; byte in a table and self-modify the
; RWTS elsewhere
2A0A-   BC 8C C0    LDY   $C08C,X
2A0D-   10 FB       BPL   $2A0A
2A0F-   B9 EC B9    LDA   $B9EC,Y
2A12-   8D CC BC    STA   $BCCC
2A15-   18          CLC
2A16-   60          RTS
2A17-   38          SEC
2A18-   60          RTS

Basically, this disk is impossible to
read or copy with anything except this
code.

So, let's use this code to read it and
copy it.

                   ~

               Chapter 6
  In Which We Attempt To Use The Disk
      As A Weapon Against Itself


*BRUN ADVANCED DEMUFFIN 1.5

[press "5" to switch to slot 5]

[press "R" to load a new RWTS module]
  --> At $B6, load "OBJ.B600-BFFF"
      from drive 1

[press "6" to switch to slot 6]

[press "C" to convert disk]

This disk is 16 sectors, and the
default options (copy the entire disk,
all tracks, all sectors) don't need to
be changed. It probably won't be able
to read track 0, but we'll jump off
that bridge when we come to it.

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======PRESS ANY KEY TO CONTINUE=======
TRK:R..................................
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:R..................................
SC1:...................................
SC2:...................................
SC3:...................................
SC4:...................................
SC5:...................................
SC6:...................................
SC7:...................................
SC8:...................................
SC9:...................................
SCA:...................................
SCB:...................................
SCC:...................................
SCD:...................................
SCE:...................................
SCF:...................................
=======================================
16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

]PR#5
...
]CATALOG,S6,D2

C1983 DSR^C#254
008 FREE

 A 002 HELLO
 A 056 GROUND.F19
 A 059 FLY.F14
 A 055 BCOMP.F19
 A 049 ELEV.F19
 A 040 TRADE.F22
 B 008 CRUNCHED CAREXT
 B 019 CRUNCHED CARINT
 B 009 CRUNCHED ELEVPIC
 B 017 CRUNCHED STORE
 B 019 CRUNCHED SMOKE
 B 023 CRUNCHED AUCTION
 B 008 CRUNCHED TABLE
 T 015 ADVICE
 T 012 ITEMS
 T 004 SONG0
 T 004 SONG1
 A 022 LOGO.F26
 A 037 DEMO.M20
 A 003 INITTEMP
 B 003 UTIL.$0D00
 B 002 SHAPE TABLE
 B 003 X
 B 006 Y
 T 004 SONG
 B 006 HELLO PRONTO-DOS
 T 002 SAVEGAME0
 T 001 SAVEGAME1

]LOAD HELLO
]LIST

 10 D$ =  CHR$ (4)
 20  TEXT : HOME
 30  PRINT
 35  PRINT D$;"BRUN HELLO PRONTO-
     DOS"
 40  REM   IN ORDER TO USE OUR AL
     TERNATE MEMORY SCHEME, THE F
     OLLOWING THREE POKES ARE NEC
     ESSARY
 46  POKE 103,49: REM  $31
 48  POKE 104,64: REM  $40
 50  POKE 16432,0
 55  PRINT D$"RUN INITTEMP"

]RUN

It briefly flashes an error message:

CAN'T EXECUTE PRONTO-DOS
DOS NOT AT NORMAL 48K LOCATION.

...but then it continues booting until
it crashes at the "demo or play game"
screen.

However, if I reboot with the DOS 3.3
System Master disk, then re-insert my
demuffined copy and re-run HELLO, it
does work. This tells me that there is
no secondary protection that relies on
the original bootloader. Once we loaded
the custom RWTS, it loaded a standard
DOS (then modified itself in-memory to
become Pronto-DOS), and the game itself
doesn't care how it got there.

That's great news, because it means I
can replace tracks 0-2 with a standard
DOS 3.3 that runs the HELLO program,
and the entire game should just work.

[Copy ][+ 8.4]
  --> COPY
    --> DOS
      --> from slot 6, drive 2
      -->   to slot 6, drive 1

[S6,D1=demuffin'd copy]
[S6,D2=newly formatted DOS 3.3 disk]

...read read read...
...write write write...

]PR#6
...game boots and loads, and it is
   glorious, except for one minor
   detail...

                   ~

               Chapter 7
     In Which We Sweat The Details


There is one minor detail, one small
"finishing touch," that would make this
crack house into a crack home.

                 --v--

T00,S00
----------- DISASSEMBLY MODE ----------
0001:A5 27          LDA   $27
0003:C9 09          CMP   #$09
0005:D0 18          BNE   $001F
0007:A5 2B          LDA   $2B
0009:4A             LSR
000A:4A             LSR
000B:4A             LSR
000C:4A             LSR
000D:09 C0          ORA   #$C0
000F:85 3F          STA   $3F
0011:A9 5C          LDA   #$5C
0013:85 3E          STA   $3E
0015:18             CLC
0016:AD FE 08       LDA   $08FE
0019:6D FF 08       ADC   $08FF
001C:20 B3 08       JSR   $08B3     <--
...

00B3:8D FE 08       STA   $08FE

; clear the screen and print
; "SPINNAKER"
00B6:20 2F FB       JSR   $FB2F
00B9:20 58 FC       JSR   $FC58
00BC:A2 09          LDX   #$09
00BE:BD E9 08       LDA   $08E9,X
00C1:9D 0E 04       STA   $040E,X
00C4:CA             DEX
00C5:10 F7          BPL   $00BE
00C7:60             RTS

                 --^--

]PR#6
...game boots and loads and prints
   "SPINNAKER" during boot just like
   the original, and it is glorious...

Quod erat liberandum.

---------------------------------------
A 4am crack                    No. 2128
------------------EOF------------------
